<?php
/**
 *+------------------
 * Lflow
 *+------------------
 * Copyright (c) 2023~2030 gitee.com/liu_guan_qing All rights reserved.本版权不可删除，侵权必究
 *+------------------
 * Author: Mr.April(405784684@qq.com)
 *+------------------
 */
declare (strict_types=1);

namespace lflow\workflow;

use lflow\entity\Order;
use lflow\entity\Process;
use lflow\entity\Task;
use lflow\model\ProcessModel;
use lflow\WorkFlowEngineAlias;
use lflow\WorkFlowException;

/**
 * 流程执行过程中所传递的执行对象，其中包含流程定义、流程模型、流程实例对象、执行参数、返回的任务列表
 *
 * @author Mr.April
 * @since  1.0
 */
class Execution extends AccessService
{
    /**
     * 容器
     */
    private WorkFlowEngine $engine;

    /**
     * 流程定义对象
     */
    private Process $process;

    /**
     * 流程实例对象
     */
    private Order $order;

    /**
     * 父流程实例
     */
    private Order $parentOrder;

    /**
     * 父流程实例节点名称
     */
    private string $parentNodeName;

    /**
     * 子流程实例节点名称
     */
    private string $childOrderId;

    /**
     * 执行参数
     */
    private string $args;

    /**
     * 操作人
     */
    private string $operator;

    /**
     * 任务
     */
    private Task $task;

    /**
     * 返回的任务列表
     */
    private array $tasks;

    /**
     * 是否已合并
     * 针对join节点的处理
     */
    private bool $isMerged = false;

    /**
     * 返回任务
     *
     * @return
     */
    public function getEngine()
    {
        return $this->engine;
    }

    /**
     * 设置任务
     *
     * @param task
     */
    public function setEngine($engine)
    {
        $this->engine = $engine;
    }

    public function execution(WorkFlowEngineAlias $engine, Process $process, Order $order, string $args)
    {
        if (empty($process) || empty($order)) {
            throw new WorkFlowException("构造Execution对象失败，请检查process、order是否为空");
        }
        $this->engine  = $engine;
        $this->process = $process;
        $this->order   = $order;
        $this->args    = $args;
    }

    /**
     * 获取流程定义对象
     *
     * @return \lflow\entity\Process
     */
    public function getProcess(): Process
    {
        return $this->process;
    }

    /**
     * 获取流程模型对象
     *
     * @return mixed
     */
    public function getModel(): ProcessModel
    {
        return $this->process->getModel();
    }

    /**
     * 获取流程实例对象
     *
     * @return \lflow\entity\Order
     */
    public function getOrder(): Order
    {
        return $this->order;
    }

    /**
     * 获取执行参数
     *
     * @return string
     */
    public function getArgs(): string
    {
        return $this->args;
    }

    /**
     * 返回任务结果集
     *
     * @return array
     */
    public function getTasks(): array
    {
        return $this->tasks ?? [];
    }

    /**
     * 添加任务集合
     *
     * @param array $tasks
     */
    public function addTasks(array $tasks): void
    {
        $this->tasks = $tasks;
    }

    /**
     * 添加任务
     *
     * @param \lflow\entity\Task $task
     */
    public function addTask(Task $task)
    {
        $this->tasks[] = $task;
    }

    /**
     * 返回当前操作人ID
     *
     * @return string
     */
    public function getOperator(): string
    {
        return $this->operator;
    }

    /**
     * 设置当前操作人ID
     *
     * @param string $operator
     */
    public function setOperator(string $operator): void
    {
        $this->operator = $operator;
    }

    /**
     * 返回任务
     *
     * @return \lflow\entity\Task|null
     */
    public function getTask(): ?Task
    {
        return $this->task ?? null;
    }

    /**
     * 设置任务
     *
     * @param \lflow\entity\Task $task
     */
    public function setTask(Task $task): void
    {
        $this->task = $task;
    }

    /**
     * 判断是否已经成功合并
     *
     * @return bool
     */
    public function isMerged(): bool
    {
        return $this->isMerged;
    }

    /**
     * 设置是否为已合并
     *
     * @param bool $isMerged
     */
    public function setMerged(bool $isMerged): void
    {
        $this->isMerged = $isMerged;
    }

    public function getParentOrder(): string
    {
        return $this->parentOrder;
    }

    public function getParentNodeName(): string
    {
        return $this->parentNodeName;
    }

    public function getChildOrderId(): string
    {
        return $this->childOrderId;
    }

    public function setChildOrderId(string $childOrderId): void
    {
        $this->childOrderId = $childOrderId;
    }

}
